package com.fufan.mvcframework.util;

import java.io.File;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.fufan.mvcframework.annocation.FufanAction;
import com.fufan.mvcframework.annocation.FufanActionForm;
import com.fufan.mvcframework.annocation.FufanMethod;
import com.fufan.mvcframework.config.ActionConfig;
import com.fufan.mvcframework.config.FormbeanConfig;

/**
 * 注解解析工具
 * @author fufan
 *
 */
public class AnnoConfigUtil {

	/**
	 * 根据mvc.xml扫描controller等
	 * @param actionConfigMap
	 * @param formbeanConfigMap
	 * @param xmlPath
	 */
	public static void readConfig(Map<String,ActionConfig> actionConfigMap, 
			Map<String,FormbeanConfig> formbeanConfigMap, String projectPath, String xmlPath){
		SAXReader reader = new SAXReader(); 
		try {
			Document document = reader.read(new File(xmlPath));
			Element rootElement = document.getRootElement();
			Element scanElement = rootElement.element("component-scan");
			
			if(scanElement == null){
				//扫描程序包所有的class
//				scanAnnotation(actionConfigMap,formbeanConfigMap, "");
				return;
			}
			
			//base-package
			String basePackage = scanElement.attributeValue("base-package");
			if(basePackage == null){
				//扫描程序包所有的class
//				scanAnnotation(actionConfigMap,formbeanConfigMap, "");
			}
			if(basePackage != null){
				String[] paths = basePackage.split(",");
				for(String path:paths){
					scanAnnotation(actionConfigMap,formbeanConfigMap, projectPath, path);
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		
	}

	/**
	 * 扫描该包下面所有的文件
	 * @param actionConfigMap
	 * @param formbeanConfigMap
	 * @param path
	 */
	private static void scanAnnotation(
			Map<String, ActionConfig> actionConfigMap,
			Map<String, FormbeanConfig> formbeanConfigMap, String projectPath, String path) {
		
		String packagePath = projectPath+"WEB-INF/classes/";
		if(path.endsWith("*")){
			packagePath = packagePath + path.substring(0,path.length()-1).replace(".", "/");
		}else{
			packagePath = packagePath + path.replace(".", "/");
		}
		
		System.out.println("packagePath:"+packagePath);
		File scanFile = new File(packagePath);
		lookupFile(actionConfigMap, formbeanConfigMap, scanFile, true);
	}
	
	/**
	 * 循环便利文件
	 * @param file
	 * @param findChildPath
	 */
	public static void lookupFile(Map<String, ActionConfig> actionConfigMap,
			Map<String, FormbeanConfig> formbeanConfigMap, File file, boolean findChildPath) {
		if (findChildPath) {
			if (file.isDirectory()) {
				File[] childrens = file.listFiles();
				if (childrens != null) {
					for (File child : childrens) {
						if (child.isDirectory()) {
							lookupFile(actionConfigMap, formbeanConfigMap,child, findChildPath);
						} else {
							// 解析文件
							addElement(actionConfigMap, formbeanConfigMap, child);
						}
					}
				}
			}

		} else {
			// 只便利一层
			if (file.isDirectory()) {
				File[] childrens = file.listFiles();
				if (childrens != null) {
					for (File child : childrens) {
						if (!child.isDirectory()) {
							// 解析文件
							addElement(actionConfigMap, formbeanConfigMap, child);
						}
					}
				}
			}
		}

	}
	
	/**
	 * 解析文件
	 * 
	 * @param file
	 */
	private static void addElement(Map<String, ActionConfig> actionConfigMap,
			Map<String, FormbeanConfig> formbeanConfigMap, File file) {
		
		String classFileName = file.getName();
		String absolutePath = file.getAbsolutePath();
		String packagepath = absolutePath.substring(absolutePath.indexOf("WEB-INF\\classes\\") + 16);
		packagepath = packagepath.replace("\\", ".");
		packagepath = packagepath.substring(0, packagepath.lastIndexOf("."));
		
		System.out.println("正在解析：" + packagepath + ".java 文件");
		try {
			Class<?> clazz = Class.forName(packagepath);

			//action method
			FufanAction fufanAction = clazz.getAnnotation(FufanAction.class);
			if (fufanAction != null) {
				
				//处理class
				String path = fufanAction.path();
				String actionForm = fufanAction.actionForm();
				
				System.out.println("path = " + path + " actionForm = "+actionForm);
				if (!path.startsWith("/")) {
					path = "/" + path;
				}
				ActionConfig actionConfig = new ActionConfig();
				actionConfig.setPath(path);
				actionConfig.setFmbean(actionForm);
				actionConfig.setClassName(packagepath);
				
				// 处理method
				Method[] methods = clazz.getDeclaredMethods();
				if (methods == null) {
					System.out.println(packagepath + "类中没有被RequestMapping注解的方法");
				} else {
					for (Method method : methods) {
						System.out.println("解析到方法：" + method.getName());

						FufanMethod fufanMethod = method.getAnnotation(FufanMethod.class);
						if (fufanMethod != null) {
							// 即被注解也被public 修饰
							System.out.println(method.getName() + "方法被注解和 被 public 修饰");
							String methodValue = fufanMethod.value();
							
							actionConfig.getMethodMap().put(methodValue, method.getName());
						} else {
							System.out.println(method.getName() + "方法未被注解");
						}
					}
				}
				
				actionConfigMap.put(path, actionConfig);
			} else {
				System.out.println(packagepath + "未被注解");
			}
			
			
			//判断ActionForm
			FufanActionForm fufanActionForm = clazz.getAnnotation(FufanActionForm.class);
			if(fufanActionForm != null){
				System.out.println(packagepath + "  "+fufanActionForm.value());
				FormbeanConfig formbeanConfig = new FormbeanConfig();
				formbeanConfig.setName(fufanActionForm.value());
				formbeanConfig.setType(packagepath);
				formbeanConfigMap.put(formbeanConfig.getName(), formbeanConfig);
			}
		} catch (ClassNotFoundException e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		Map<String,ActionConfig> actionConfigMap = new HashMap<String,ActionConfig>();
		Map<String,FormbeanConfig> formbeanConfigMap = new HashMap<String,FormbeanConfig>();
		String path = "com.fufan.demo.*";
		
//		scanAnnotation(actionConfigMap, formbeanConfigMap, path);
	}
}
